package com.cyy.common.exception;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import com.cyy.common.domain.Response;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.stream.Collectors;

/**
 * @author caoyunyou
 */
@Slf4j
@ControllerAdvice(basePackages = "com.cyy")
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Response methodArgumentNotValidExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException e) {
        String message = e.getBindingResult().
                getFieldErrors()
                .stream().map(error -> error.getField() + ":" + error.getDefaultMessage())
                .collect(Collectors.joining(";"));
        log.error("接口{}出现异常,异常摘要:", request.getRequestURI(), e);
        return Response.failed().msg(message);
    }

    @ExceptionHandler(BindException.class)
    public Response handleRequestExceptions(HttpServletRequest request, Exception e) {
        if (e instanceof BindException) {
            StringBuilder msg = new StringBuilder();
            for (FieldError error : ((BindException) e).getFieldErrors()) {
                msg.append("字段[").append(error.getField()).append("]的值[").append(error.getRejectedValue()).append("]无效;");
            }
            return Response.failed().msg(msg.toString());
        }
        String message = StringUtils.isBlank(e.getMessage()) ? "请求参数异常" : e.getMessage();
        log.error("接口{}出现异常,异常摘要:", request.getRequestURI(), e);
        return Response.failed().msg(message);
    }

    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    @ResponseBody
    public Response missingServletRequestParameterExceptionHandler(HttpServletRequest request, Exception e) {
        MissingServletRequestParameterException bindException = (MissingServletRequestParameterException) e;
        log.warn("接口{}出现业务异常,异常摘要:", request.getRequestURI(), e);
        return Response.failed().msg(String.format("缺少必要参数[%s]", bindException.getParameterName()));
    }

    @ExceptionHandler(value = NotLoginException.class)
    @ResponseBody
    public Response notLoginExceptionHandler(HttpServletRequest request, Exception e) {
        log.error("接口{}出现业务异常,异常摘要:{}", request.getRequestURI(), e.getMessage());
        return new Response().code(HttpStatus.UNAUTHORIZED).msg(e.getMessage());
    }

    @ExceptionHandler(value = NotPermissionException.class)
    @ResponseBody
    public Response notPermissionExceptionHandler(HttpServletRequest request, Exception e) {
        log.error("接口{}出现业务异常,异常摘要:{}", request.getRequestURI(), e.getMessage());
        return new Response().code(HttpStatus.FORBIDDEN).msg(e.getMessage());
    }

    @ExceptionHandler(value = ProcessException.class)
    @ResponseBody
    public Response processExceptionHandler(HttpServletRequest request, Exception e) {
        String exceptionMeg = e.getMessage();
        log.warn("接口{}出现业务异常,异常摘要:{}", request.getRequestURI(), e.getMessage());
        return new Response().code(HttpStatus.INTERNAL_SERVER_ERROR).msg(exceptionMeg);
    }


    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Response otherExceptionHandler(HttpServletRequest request, Exception e) {
        String exceptionMeg = String.format("接口[%s]出现异常,异常摘要:%s",
                request.getRequestURI(),
                e.getMessage());
        log.error("接口{}出现异常,异常摘要:", request.getRequestURI(), e);
        return Response.failed().msg(exceptionMeg);
    }


}
